package org.jheuristics.ga.operators.closures;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.epanetgrid.otimizacao.ag.ViaveisSelector;
import org.epanetgrid.otimizacao.log.AGLogger;
import org.jheuristics.Individual;
import org.jheuristics.ga.DefaultPopulation;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.Population;
import org.jheuristics.ga.operators.ClosureSelection;
import org.jheuristics.ga.operators.selectors.BestIndividualsViaveisSelector;
import org.jheuristics.ga.operators.selectors.NonDominatedSelector;


public class SPEA3SelectionClosure implements ClosureSelection {

	private AGLogger logger = AGLogger.getInstance();
	
	public SPEA3SelectionClosure() {
	}

	/**
	 * TODO
	 *
	 * @param selected
	 * @param population
	 * @param status
	 * @param config
	 * @see org.jheuristics.ga.operators.ClosureSelection#execute(org.jheuristics.ga.Population, org.jheuristics.ga.Population, org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
	 */
	public void execute(Population selected, Population pop, GAStatus status, GAConfig config) {
		//population = pop de entrada do corte contem inviaveis...
		//selected = ind que sobraram apos o corte

		int quantFuncoes = ((List)selected.toIndividualArray()[0].getDataApplication()).size();
		
		Individual[] indsViaveis = new ViaveisSelector().select(pop, 0, null, null);
		
		//Limpando a prox pop
		pop.clear();
		
		DefaultPopulation popViaveis = new DefaultPopulation();
		popViaveis.addIndividuals(indsViaveis);
		
		Individual[] indsNaoDominadosViaveis = new NonDominatedSelector().select(popViaveis, 0, null, null);
		DefaultPopulation popNaoDominadosViaveis = new DefaultPopulation();
		popNaoDominadosViaveis.addIndividuals(indsNaoDominadosViaveis);
		
		//bests viaveis =D
		Individual[] bests = new BestIndividualsViaveisSelector().select(popNaoDominadosViaveis, 1, null, null);
		
		logger.debug("bests: "+Arrays.toString(bests));
		
		selected.sort();
		List<Individual> inseridos = new LinkedList<Individual>();
		List<Individual> removidos = new LinkedList<Individual>();
		for(int i = 0; i < quantFuncoes; i++) {
			removidos.add(selected.getIndividual(selected.size()-1));
		}
		
		for(int i = 0; i < bests.length; i++) {
			inseridos.add(bests[i]);
		}
		
		for (Individual individual : removidos) {
			selected.removeIndividual(individual);
		}
		
		for (Individual individual : inseridos) {
			selected.addIndividual(individual);
		}
		
//		for (Individual bestInd : bests) {
//			if(!selected.contains(bestInd)) {
//				removidos.add(selected.getIndividual(selected.size()-1));
//				selected.removeIndividual(selected.size()-1);
//				selected.addIndividual(bestInd);
//				selected.sort();
//				inseridos.add(bestInd);
//			}
//		}
		
//		if(inseridos.size() == 0) {
//			SPLogger.getInstancia().log(SPLogger.OTIMIZACAO, SPLogger.DEBUG, "Todos os m�nimos j� estavam na popula��o.");
//		}else {
			StringBuffer buffer = new StringBuffer("\nInserindo m�nimos das fun��es atrav�s do elitismo.\nIndiv�duos inseridos:\n");
			
			for (Individual individual : inseridos) {
				buffer.append(individual);
				buffer.append("\n");
			}
			
			buffer.append("Indiv�duos removidos:\n");
			
			for (Individual individual : removidos) {
				buffer.append(individual);
				buffer.append("\n");
			}
			
			logger.debug(buffer);
//		}
		
	}

}
